﻿using System;
using System.Diagnostics;
using System.Text;
using log4net;

namespace TimeMachine.Engine.Vcs.Svn
{
	public class SvnExecutor : ISvnExecutor
	{
		private static readonly ILog log = LogManager.GetLogger(typeof (SvnExecutor));

		public string Execute(string formatArgs, params object[] values)
		{
			return Execute(string.Format(formatArgs, values));
		}

		public void ExecuteToFile(string resultFilename, string formatArgs, params object[] values)
		{
			ExecuteToFile(resultFilename, string.Format(formatArgs, values));
		}

        public Exception CreateAndLog(string messageFormat, params object[] args)
        {
            string message = string.Format(messageFormat, args);
            log.Error(message);
            return new Exception(message);
        }

		public void ExecuteToFile(string resultFilename, string args)
		{
			args = "/C svn.exe " +args + " >" + resultFilename;
            log.InfoFormat("svn.exe {0}", args);
			Process process = Process.Start("cmd.exe", args);
            if (process == null)
                throw CreateAndLog("Не получилось запустить процесс cmd.exe {0}\n", args);
			process.WaitForExit();
			if(process.ExitCode != 0)
			    throw CreateAndLog("Ошибка при запуске {0}\nExitCode: {1}", args, process.ExitCode);
		}

		public string Execute(string args)
		{
			return ExecuteInternal(args, true);
		}

		private static string ExecuteInternal(string args, bool redirect)
		{
			GC.Collect();
			log.InfoFormat("svn.exe {0}", args);
			Encoding enc = args.Contains("--xml") ? Encoding.UTF8 : Console.OutputEncoding;
			var processInfo =
				new ProcessStartInfo("svn.exe", args)
					{
						CreateNoWindow = true,
						RedirectStandardOutput = redirect,
						RedirectStandardError = redirect,
						UseShellExecute = !redirect
					};
			if(redirect) processInfo.StandardOutputEncoding = enc;
			using (Process process = Process.Start(processInfo))
			{
				if (process == null)
					throw new Exception("Не удалось вызвать svn.exe");
				string output = redirect ? process.StandardOutput.ReadToEnd() : null;
				process.WaitForExit();
				if (process.ExitCode != 0)
				{
					string error = redirect ? process.StandardError.ReadToEnd() : null;
					string message = string.Format(
						"Ошибка при запуске svn.exe {0}\n{1}\nExitCode: {2}",
						args, error, process.ExitCode);
					log.Error(message);
					throw new Exception(message);
				}
				log.DebugFormat("svn.exe {0}\r\nРезультат выполнения:\r\n{1}", args, output);
				return output;
			}
		}
	}

	public interface ISvnExecutor
	{
		string Execute(string formatArgs, params object[] values);
		void ExecuteToFile(string resultFilename, string formatArgs, params object[] values);
	}
}